package Twitim::Notification;

use strict;
use warnings;
use Glib qw(TRUE FALSE);
use HTML::Entities;
use Twitim::Twitim;
use Twitim::L10N;
use Twitim::NetBase;

sub new {
    my $this  = shift;
    my $class = ref($this) || $this;
    my $self  = {@_};

    if ( eval 'use GStreamer -init; 1;' ? TRUE : FALSE ) {
        $self->{'gstreamer_is_ok'} = 1;
    }

    if ( eval 'use Net::DBus::GLib; 1;' ? TRUE : FALSE ) {
        $self->{'dbus_is_ok'}      = 1;
        $self->{'notify_obj'}      = _setup_notification();
        $self->{'screensaver_obj'} = _setup_dbus_screensaver();
        $self->{'actions_is_ok'}   = _check_notify_functions();
    }

    bless $self, $class;
}

sub notify {
    my ( $self, $tabname, $option, $jid, $body, $id ) = @_;

    return
        unless ( exists $main::CFG->{$tabname}
        && $option ne 'all but Timeline' );

    if ( $main::CFG->{$tabname}->{'notification_popup'} ) {
        $self->_show_popup(
            $tabname,
            $jid,
            $body,
            $id,
            $main::CFG->{$tabname}->{'notification_expire_type'},
            $main::CFG->{$tabname}->{'notification_expire_time'}
        );
    }

    if ( $main::CFG->{$tabname}->{'notification_sound'} ) {
        $self->_play_sound();
        # $MAINWIN->set_urgency_hint(TRUE);
    }
}

sub dbus_is_ok {
    my $self = shift;
    return $self->{'dbus_is_ok'};
}

sub sound_is_ok {
    my $self   = shift;
    my $result = ( $main::CFG->{'default'}->{'sound_command'}
            || $self->{'gstreamer_is_ok'} ) ? 1 : 0;

    return $result;
}

sub _show_popup {
    my ( $self, $tabname, $jid, $body, $id, $expire_type, $expire_time ) = @_;

    return unless ( $self->{'dbus_is_ok'} );

    my $icon   = Twitim::NetBase->get_icon($jid);
    my $pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($icon);
    my $len = 48;
    if ( $pixbuf->get_height > $len || $pixbuf->get_width > $len ) {
        my $dest = $pixbuf->scale_simple( $len, $len, 'GDK_INTERP_BILINEAR');
        $dest->save( $icon, 'png' );
    }

    chomp($body);
    $body = encode_entities( $body, '<>&' );

    #my $re_url = q{s?https?://[-_.!~*'a-zA-Z0-9;/?:@&=+$,%#]+};
    #$body =~ s|($re_url)|<a href=\"$1\">$1</a>|g;
    #$body =~ s|\B@([a-zA-Z0-9_]+)|@<a href=\"$main::TWITTER_URL$1\">$1</a>|g;

    my $keywords = $main::MAINWIN->get_pickup_keywords($tabname);
    if ( $keywords && $body !~ />.*($keywords).*</gi ) {
        $body =~ s!($keywords)!<i>$1</i>!gi;
    }

    my $actions
        = ( substr( $id, 0, 2 ) ne "d_" )
        ? [ "reply $jid $id", l10n("Reply") ]
        : [ "dm $jid", l10n("Direct Message") ];
    push @$actions, "browse $jid $id", l10n("Open This Status Page");

    $expire_type ||= 0;
    $expire_time ||= 0;

    # NotifyOSD not support actions and 0 expire time.
    if (! $self->{'actions_is_ok'}) {
        $actions = [];
        $expire_time = -1 if $expire_time == 0;
    } else {
        # for actions
        $body .= "\n"; 
    }

    if ( !defined $self->{'screensaver_obj'} ) {
        $self->{'screensaver_obj'} = _setup_dbus_screensaver();
    }
    my $session_idle = defined $self->{'screensaver_obj'} ? 
        #$self->{'screensaver_obj'}->GetSessionIdle() : 0;
        $self->{'screensaver_obj'}->GetActive() : 0;

    my $expiration
        = (    $main::CFG->{$tabname}->{'notification_expire_in_iding'}
            && $session_idle ) ? 0
        : ( $expire_type < 2 ) ? $expire_type - 1
        :                        $expire_time * 1000;

    my $username = Twitim::NetBase->get_username($jid);

    my $notify_id
        = $self->{'notify_obj'}
        ->Notify( "Twitim", 0, $icon, $username, $body, 
        $actions, {}, $expiration );

    # print "$jid: $expire_type - $expire_time ($expiration)\n"
}

sub _setup_notification {
    my $bus     = Net::DBus::GLib->session;
    my $service = $bus->get_service('org.freedesktop.Notifications');
    my $obj     = $service->get_object( '/org/freedesktop/Notifications',
        'org.freedesktop.Notifications' );
    $obj->connect_to_signal(
        'ActionInvoked',
        sub {
            my ( $id, $action ) = @_;
            my @args = split / /, $action;

            if ( $args[0] eq "browse" ) {
                open_url( $main::TWITTER_URL . $args[1] . '/status/' . $args[2]);
            }
            elsif ( $args[0] eq "reply" ) {
                $main::MAINWIN->insert_reply_name( $args[1], $args[2] );
            }
            elsif ( $args[0] eq "dm" ) {
                $main::MAINWIN->insert_dm_name( $args[1] );
            }
        }
    );
    return $obj;
}

sub _check_notify_functions {
    my $method = shift;
    $method ||= 'actions';

    my $bus = Net::DBus::GLib->session;
    my $service;

    eval { $service = $bus->get_service('org.freedesktop.Notifications'); };

    my $obj
        = $@ ? undef : $service->get_object( '/org/freedesktop/Notifications',
        'org.freedesktop.Notifications' );
    my $capabilities = $obj->GetCapabilities();
    my $result = grep( /$method/, @$capabilities ) ? 1 : 0;

    #print "$result\n";
    return $result;
}

sub _setup_dbus_screensaver {
    my $bus     = Net::DBus::GLib->session;
    my $service;

    eval {
        $service = $bus->get_service('org.gnome.ScreenSaver');
    };

    my $obj = $@ ? undef : $service->get_object(
        '/org/gnome/ScreenSaver', 'org.gnome.ScreenSaver' );
    return $obj; 
}

sub _play_sound {
    my ( $self, $file ) = @_;

    my $config = $main::CFG->{'default'};

    return if ( !$config->{'sound_file'} || !-r $config->{'sound_file'} );

    $file ||= $config->{'sound_file'};

    if ( $config->{'sound_command'} && -x $config->{'sound_command'} ) {
        system("$config->{'sound_command'} $file 2> /dev/null &");
        return;
    }

    return unless ( $self->{'gstreamer_is_ok'} );

    my $loop = Glib::MainLoop->new();
    my $play = GStreamer::ElementFactory->make( playbin => "play" );

    $play->set( uri => Glib::filename_to_uri $file, "localhost" );
    $play->get_bus()->add_watch( \&_play_sound_callback, $loop );
    $play->set_state("playing") or die "Could not start playing";

    $loop->run();
    $play->set_state("null");
}

sub _play_sound_callback {
    my ( $bus, $message, $loop ) = @_;

    if ( $message->type & "error" ) {
        warn $message->error;
        $loop->quit();
    }
    elsif ( $message->type & "eos" ) {
        $loop->quit();
    }
    return TRUE;
}

1;
